package dletc.死锁;
/*
死锁代码要会写。
一般面试官要求你会写。
只有会写的，才会在以后的开发中注意这个事儿。
因为死锁很难调试。

注意：synchronized在开发中，最好不好开发使用。不小心会出现死锁。

死锁出现的四个必要条件：
    1.互斥条件：一个资源每次只能被一个进程使用；
    2.请求与保持条件：一个进程因请求资源而阻塞时，对已获得的资源保持不放；
    3.不剥夺条件：进程已获得的资源，在未使用完之前，不能强制剥夺；
    4.循环等待条件：若干进程之间形成一种头尾相接的循环等待资源关系
                  举例：有2个资源A，B，线程1先拿A在拿B，线程2先拿B在拿A，形成循环等待。
 */
public class DeadLock {
    public static void main(String[] args) {
        Object o1 = new Object();
        Object o2 = new Object();

        // t1和t2两个线程共享o1,o2
        Thread t1 = new MyThread1(o1,o2);
        Thread t2 = new MyThread2(o1,o2);

        t1.start();
        t2.start();
    }
}

class MyThread1 extends Thread{
    Object o1;
    Object o2;
    public MyThread1(Object o1,Object o2){
        this.o1 = o1;
        this.o2 = o2;
    }
    public void run(){
        synchronized (o1){
        	//如果不休眠的话，可能会正常执行，因为ti现场抢到了时间片，先执行了锁o1/o2在释放，或t2先执行。
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (o2){

            }
        }
    }
}

class MyThread2 extends Thread {
    Object o1;
    Object o2;
    public MyThread2(Object o1,Object o2){
        this.o1 = o1;
        this.o2 = o2;
    }
    public void run(){
        synchronized (o2){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (o1){

            }
        }
    }
}
